package cn.qingyun.gis.modules.express.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReUtil;
import cn.qingyun.gis.modules.express.constant.ExpressStatus;
import cn.qingyun.gis.modules.express.entity.ExportHandleExpressExcel20230727;
import cn.qingyun.gis.modules.express.entity.ExpressProofreadHandle;
import cn.qingyun.gis.modules.express.entity.ExpressRegionHandle;
import cn.qingyun.gis.modules.express.entity.dto.ExpressRegionChangeDto;
import cn.qingyun.gis.modules.express.mapper.ExpressProofreadHandleMapper;
import cn.qingyun.gis.modules.express.service.IExpressProofreadHandleService;
import cn.qingyun.gis.modules.express.service.IExpressRegionHandleService;
import cn.qingyun.gis.modules.express.service.IExpressRegionService;
import cn.qingyun.gis.modules.express.util.SyncTool;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.locationtech.jts.geom.Coordinate;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.regex.Pattern;

import static cn.qingyun.gis.modules.express.util.GeoTool.getCoordinateArray;
import static cn.qingyun.gis.modules.express.util.GeoTool.withinAndIntersects;

/**
 * <p>
 * 快递勘误(处理) 服务实现类
 * </p>
 *
 * @author miyunguo
 * @since 2023-08-30
 */
@Service
@Slf4j
public class ExpressProofreadHandleServiceImpl extends ServiceImpl<ExpressProofreadHandleMapper, ExpressProofreadHandle> implements IExpressProofreadHandleService {

    @Resource
    private IExpressProofreadHandleService iExpressProofreadHandleService;
    @Resource
    private IExpressRegionHandleService iExpressRegionHandleService;
    @Resource
    private IExpressRegionService iExpressRegionService;

    @Resource
    private ExpressProofreadHandleMapper expressProofreadHandleMapper;

    @Override
    public void handleExpressProofred() {
        //1.获取业务区划（处理）中网格编码与网格名称
        QueryWrapper<ExpressRegionHandle> expressRegionHandleQueryWrapper = new QueryWrapper<>();
        expressRegionHandleQueryWrapper.lambda().
                select(ExpressRegionHandle::getCode, ExpressRegionHandle::getName, ExpressRegionHandle::getGeometry).
                eq(ExpressRegionHandle::getLevel, "4");
        List<ExpressRegionHandle> expressRegionHandles = iExpressRegionHandleService.list(expressRegionHandleQueryWrapper);
        List<ExpressRegionChangeDto> expressRegionChangeDtos = Lists.newArrayList();

        //2.将多边形边界 -> 单边边界数组
        for (ExpressRegionHandle expressRegionHandle : expressRegionHandles) {
            ExpressRegionChangeDto expressRegionChangeDto = new ExpressRegionChangeDto();
            BeanUtil.copyProperties(expressRegionHandle, expressRegionChangeDto);

            List<String> res = Lists.newArrayList();
            if (ObjectUtil.isNotEmpty(expressRegionHandle.getGeometry())) {
                //使用正则匹配获取 (?<=\()[^)]+ 获取到每个面的边界数据
                res = ReUtil.findAll(Pattern.compile("(?<=\\()[^)]+", Pattern.MULTILINE), expressRegionHandle.getGeometry(), 0);
            }
            expressRegionChangeDto.setGeometryList(res);
            expressRegionChangeDtos.add(expressRegionChangeDto);
        }

        //3.若原快递地址经纬度不存在，无需进行网格匹配
        QueryWrapper<ExpressProofreadHandle> expressProofreadHandleQueryWrapper = new QueryWrapper<>();
        expressProofreadHandleQueryWrapper.lambda().
                isNotNull(ExpressProofreadHandle::getLon).
                isNotNull(ExpressProofreadHandle::getLat);

        int count = iExpressProofreadHandleService.count(expressProofreadHandleQueryWrapper);
        int pages = (count / 1000) + 1;
        SyncTool.doSync(pages, i -> {

                    //4.分页获取待处理快递地址信息
                    Page<ExpressProofreadHandle> page = new Page<>(i, 1000);
                    List<ExpressProofreadHandle> expressProofreadHandles = iExpressProofreadHandleService.page(page, expressProofreadHandleQueryWrapper).getRecords();
                    List<ExpressProofreadHandle> updateRecords = Lists.newArrayList();
                    //5.根据每个站点经纬度进行网格匹配
                    for (ExpressProofreadHandle expressData : expressProofreadHandles) {
                        if (ExpressStatus.UN_MATCH.equals(expressData.getMatchStatus())) { //当前快递地址从未进行匹配
                            boolean state = false;
                            //依序遍历快递地址对业务区划网格进行匹配
                            for (ExpressRegionChangeDto expressRegionChangeDto : expressRegionChangeDtos) {
                                Coordinate point = new Coordinate(expressData.getLon().doubleValue(), expressData.getLat().doubleValue());
                                //5.1 默认不匹配
                                boolean flag = false;
                                //5.2 判断当前快递地址是否在某一个网格边界内
                                if (ObjectUtil.isNotEmpty(expressRegionChangeDto.getGeometryList())) { //当前网格边界列表不为空
                                    for (String geometry : expressRegionChangeDto.getGeometryList()) {
                                        Coordinate[] coordinateArray = getCoordinateArray(geometry);
                                        flag = withinAndIntersects(coordinateArray, point);

                                        if (flag) { //如果有网格边界匹配成功，则退出匹配
                                            break;
                                        }
                                    }
                                    //5.3 若网格边界匹配成功，无需进行其他业务区划匹配
                                    if (flag) {
                                        expressData.setMatchGridId(expressRegionChangeDto.getCode());
                                        expressData.setMatchGridName(expressRegionChangeDto.getName());
                                        expressData.setSuccessStatus(ExpressStatus.SUCCESS_MATCH); //修改为成功匹配状态
                                        state = true;
                                        break;
                                    }
                                }

                            }
                            expressData.setMatchStatus(ExpressStatus.MATCH); //修改为已匹配状态
                            updateRecords.add(expressData);
                            log.debug(String.format("%s-经纬度（%s,%s）匹配%s", expressData.getExpressName(), expressData.getLon(), expressData.getLat(), state ? "成功" : "失败"));

                        }
                    }
                    // 批量导入匹配之后数据
                    iExpressProofreadHandleService.updateBatchById(updateRecords);

                    //匹配进度查询
                    QueryWrapper<ExpressProofreadHandle> countQuery = new QueryWrapper<>();
                    countQuery.lambda().eq(ExpressProofreadHandle::getMatchStatus, "1");
                    int matchCount = iExpressProofreadHandleService.count(countQuery);
            log.debug(String.format("====已处理快递数据%s.剩余%s条数据====", matchCount, count - matchCount));
                }
        );
        log.debug(String.format("====一共处理%s快递数据====", count));
    }

    @Override
    public IPage<ExportHandleExpressExcel20230727> exportExpressHandleExcelBatch(Page<ExportHandleExpressExcel20230727> page) {
        return expressProofreadHandleMapper.exportExpressHandleExcelBatch(page);
    }

    @Override
    public void handleBlankExpressProofred() {
        // 获取到新网格无法匹配的快递数据列表
        QueryWrapper<ExpressProofreadHandle> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().
                isNull(ExpressProofreadHandle::getMatchGridId).isNull(ExpressProofreadHandle::getMatchGridName);
        //List<ExpressProofreadHandle> blankGridList = expressProofreadHandleMapper.selectList(queryWrapper);
        List<ExpressRegionHandle> regionHandleList = iExpressRegionHandleService.list();

        int count = iExpressProofreadHandleService.count(queryWrapper);
        int pages = (count / 1000) + 1;
        SyncTool.doSync(pages, i -> {
            Page<ExpressProofreadHandle> page = new Page<>(i, 1000);
            List<ExpressProofreadHandle> blankGridList = iExpressProofreadHandleService.page(page, queryWrapper).getRecords();
            List<ExpressProofreadHandle> updateRecords = Lists.newArrayList();
            // 依次遍历快递数据，查看老网格是否存在与新业务规划数据中
            for (ExpressProofreadHandle blankGrid : blankGridList) {
                for (ExpressRegionHandle regionHandle : regionHandleList) {
                    /*if(ObjectUtil.isNotEmpty(blankGrid.getGridEncoding()) && blankGrid.getGridEncoding().equals(regionHandle.getCode())){
                        blankGrid.setMatchGridId(blankGrid.getGridEncoding()); //将老网格编码进行新网格编码填充
                        blankGrid.setMatchGridName(regionHandle.getName());//将老网格名称进行填充新网格名称填充
                        blankGrid.setMatchStatus(ExpressStatus.MATCH_OLD_NEW); //设置为2
                    }*/
                    if (ObjectUtil.isNotEmpty(blankGrid.getGridName()) && blankGrid.getGridName().equals(regionHandle.getName())) {
                        blankGrid.setMatchGridId(regionHandle.getCode()); //将老网格编码进行新网格编码填充
                        blankGrid.setMatchGridName(regionHandle.getName()); //将老网格名称进行填充新网格名称填充
                        blankGrid.setMatchStatus(ExpressStatus.MATCH_OLD_NEW_NAME); //设置为3
                    }
                }
                updateRecords.add(blankGrid);
            }
            //成批修改到数据库
            iExpressProofreadHandleService.updateBatchById(updateRecords);
        });

        log.debug("快递新数据网格{}条数据填充完毕", count);
    }


}
